package com.music.note_android.ui.editor

import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**
 * 手势处理器
 * 负责处理画布上的各种手势操作，包括绘制、缩放、拖拽、双击等
 */
class GestureHandler {
    
    // 手势检测器
    private var gestureDetector: GestureDetector? = null
    private var scaleGestureDetector: ScaleGestureDetector? = null
    
    // 当前手势状态
    private var currentGestureMode = GestureMode.DRAWING
    
    // 多点触控状态
    private var pointerCount = 0
    private var isMultiTouch = false
    
    // 拖拽相关
    private var isDragging = false
    private var lastDragX = 0f
    private var lastDragY = 0f
    private var dragThreshold = 10f // 拖拽阈值
    
    // 缩放相关
    private var isScaling = false
    private var scaleFactor = 1.0f
    private var minScale = 0.1f
    private var maxScale = 5.0f
    
    // 手势状态
    private var isPanning = false
    private var isDrawing = false
    private var gestureStartTime = 0L
    
    // 双指手势相关
    private var lastTwoFingerCenterX = 0f
    private var lastTwoFingerCenterY = 0f
    private var lastTwoFingerDistance = 0f
    
    // 手势参数
    private var minScaleFactor = 0.1f
    private var maxScaleFactor = 10.0f
    private var scaleVelocityThreshold = 0.01f
    private var panVelocityThreshold = 100f
    
    // 双击检测
    private var lastTapTime = 0L
    private var doubleTapTimeout = 300L // 双击超时时间
    
    // 长按检测
    private var isLongPressing = false
    private var longPressTimeout = 500L // 长按超时时间
    
    // 手势回调接口
    private var gestureListener: GestureCallback? = null
    
    /**
     * 手势模式枚举
     */
    enum class GestureMode {
        DRAWING,    // 绘制模式
        NAVIGATION, // 导航模式（拖拽、缩放）
        ERASING     // 擦除模式
    }
    
    /**
     * 手势事件监听接口
     */
    interface GestureCallback {
        // 绘制相关
        fun onDrawingStart(x: Float, y: Float, pressure: Float)
        fun onDrawingMove(x: Float, y: Float, pressure: Float)
        fun onDrawingEnd()
        
        // 导航相关
        fun onCanvasDrag(dx: Float, dy: Float)
        fun onCanvasScale(scaleFactor: Float, focusX: Float, focusY: Float)
        fun onCanvasDoubleTap(x: Float, y: Float)
        
        // 工具相关
        fun onToolLongPress(x: Float, y: Float)
        fun onEraserMove(x: Float, y: Float)
        
        // 手势状态
        fun onGestureModeChanged(mode: GestureMode)
        
        // 增强的手势回调
        fun onPanStart(x: Float, y: Float)
        fun onPanEnd(velocityX: Float, velocityY: Float)
        fun onScaleStart(focusX: Float, focusY: Float)
        fun onScaleEnd(velocity: Float)
        fun onFling(velocityX: Float, velocityY: Float)
        fun onGestureStateChanged(newMode: GestureMode)
    }
    
    /**
     * 初始化手势处理器
     */
    fun initialize(view: View) {
        // 创建手势检测器
        gestureDetector = GestureDetector(view.context, GestureListener())
        scaleGestureDetector = ScaleGestureDetector(view.context, ScaleListener())
        
        // 设置手势检测器参数
        gestureDetector?.setOnDoubleTapListener(DoubleTapListener())
    }
    
    /**
     * 处理触摸事件
     */
    fun handleTouchEvent(event: MotionEvent): Boolean {
        // 更新触摸点数量
        updatePointerCount(event)
        
        // 在绘画模式下，单指操作优先处理绘画事件
        if (currentGestureMode == GestureMode.DRAWING && !isMultiTouch) {
            val drawingHandled = handleDrawingGesture(event)
            if (drawingHandled) {
                // 更新绘画状态
                isDrawing = when (event.action) {
                    MotionEvent.ACTION_DOWN -> true
                    MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> false
                    else -> isDrawing
                }
                return true
            }
        }
        
        // 只有在多指触控时才让缩放手势检测器处理
        val scaleHandled = if (isMultiTouch) {
            scaleGestureDetector?.onTouchEvent(event) ?: false
        } else {
            false
        }
        
        // 如果正在缩放，不处理其他手势
        if (isScaling) {
            return true
        }
        
        // 根据当前模式处理特定手势（非绘画模式或多指操作）
        val modeHandled = when (currentGestureMode) {
            GestureMode.DRAWING -> false // 单指绘画已在上面处理
            GestureMode.NAVIGATION -> handleNavigationGesture(event)
            GestureMode.ERASING -> handleErasingGesture(event)
        }
        
        // 让基础手势检测器处理（但不影响绘画）
        val gestureHandled = if (currentGestureMode != GestureMode.DRAWING || isMultiTouch) {
            gestureDetector?.onTouchEvent(event) ?: false
        } else {
            false
        }
        
        // 处理精确的手势识别
        val preciseHandled = handlePreciseGesture(event)
        
        return scaleHandled || gestureHandled || modeHandled || preciseHandled
    }
    
    /**
     * 处理精确手势识别
     */
    private fun handlePreciseGesture(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // 记录初始触摸点和时间
                lastDragX = event.x
                lastDragY = event.y
                gestureStartTime = System.currentTimeMillis()
                return false
            }
            MotionEvent.ACTION_MOVE -> {
                // 单指操作时不进行任何模式切换，确保单指只用于绘画
                // 只有多指操作才允许切换到导航模式
                return false
            }
        }
        return false
    }
    
    /**
     * 更新触摸点数量
     */
    private fun updatePointerCount(event: MotionEvent) {
        pointerCount = event.pointerCount
        isMultiTouch = pointerCount > 1
        
        // 多点触控时自动切换到导航模式
        if (isMultiTouch && currentGestureMode == GestureMode.DRAWING) {
            // 结束当前绘制
            gestureListener?.onDrawingEnd()
            setGestureMode(GestureMode.NAVIGATION)
        }
        
        // 单点触控时切换回绘画模式（如果之前是导航模式且不在缩放状态）
        if (!isMultiTouch && currentGestureMode == GestureMode.NAVIGATION && !isScaling) {
            when (event.actionMasked) {
                MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_UP -> {
                    setGestureMode(GestureMode.DRAWING)
                }
            }
        }
        
        // 更新双指手势数据
        if (isMultiTouch && pointerCount >= 2) {
            updateTwoFingerGestureData(event)
        }
    }
    
    /**
     * 更新双指手势数据
     */
    private fun updateTwoFingerGestureData(event: MotionEvent) {
        if (event.pointerCount >= 2) {
            // 计算双指中心点
            val centerX = (event.getX(0) + event.getX(1)) / 2f
            val centerY = (event.getY(0) + event.getY(1)) / 2f
            
            // 计算双指间距
            val dx = event.getX(1) - event.getX(0)
            val dy = event.getY(1) - event.getY(0)
            val distance = kotlin.math.sqrt(dx * dx + dy * dy)
            
            lastTwoFingerCenterX = centerX
            lastTwoFingerCenterY = centerY
            lastTwoFingerDistance = distance
        }
    }
    
    /**
     * 处理绘制手势
     */
    private fun handleDrawingGesture(event: MotionEvent): Boolean {
        // 多点触控时不处理绘制
        if (isMultiTouch) {
            return false
        }
        
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                gestureListener?.onDrawingStart(event.x, event.y, event.pressure)
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                gestureListener?.onDrawingMove(event.x, event.y, event.pressure)
                return true
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                gestureListener?.onDrawingEnd()
                return true
            }
        }
        
        return false
    }
    
    /**
     * 处理导航手势
     */
    private fun handleNavigationGesture(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
                if (isMultiTouch && event.pointerCount >= 2) {
                    // 初始化双指中心点
                    updateTwoFingerGestureData(event)
                }
                isDragging = false
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                // 只有在非缩放且多指触控时才允许拖拽
                if (!isScaling && isMultiTouch && event.pointerCount >= 2) {
                    // 计算当前双指中心点
                    val currentCenterX = (event.getX(0) + event.getX(1)) / 2f
                    val currentCenterY = (event.getY(0) + event.getY(1)) / 2f
                    
                    // 计算双指中心点的移动距离
                    val dx = currentCenterX - lastTwoFingerCenterX
                    val dy = currentCenterY - lastTwoFingerCenterY
                    
                    // 检查是否超过拖拽阈值
                    if (!isDragging && (abs(dx) > dragThreshold || abs(dy) > dragThreshold)) {
                        isDragging = true
                    }
                    
                    if (isDragging) {
                        // 实时拖拽，立即更新画布位置
                        gestureListener?.onCanvasDrag(dx, dy)
                    }
                    
                    // 更新双指中心点
                    lastTwoFingerCenterX = currentCenterX
                    lastTwoFingerCenterY = currentCenterY
                }
                return true
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP, MotionEvent.ACTION_CANCEL -> {
                isDragging = false
                // 单点触控结束后切换回绘制模式
                if (!isMultiTouch && currentGestureMode == GestureMode.NAVIGATION) {
                    setGestureMode(GestureMode.DRAWING)
                }
                return true
            }
        }
        
        return false
    }
    
    /**
     * 处理擦除手势
     */
    private fun handleErasingGesture(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
                gestureListener?.onEraserMove(event.x, event.y)
                return true
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                // 擦除结束，可能切换回绘制模式
                setGestureMode(GestureMode.DRAWING)
                return true
            }
        }
        
        return false
    }
    
    /**
     * 基础手势监听器
     */
    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
        private var downTime = 0L
        private var downX = 0f
        private var downY = 0f
        private var panStartTime = 0L
        private var panStartX = 0f
        private var panStartY = 0f
        
        override fun onDown(e: MotionEvent): Boolean {
            downTime = System.currentTimeMillis()
            downX = e.x
            downY = e.y
            panStartTime = System.currentTimeMillis()
            panStartX = e.x
            panStartY = e.y
            return true
        }
        
        override fun onSingleTapUp(e: MotionEvent): Boolean {
            // 精确的单击检测
            val tapDuration = System.currentTimeMillis() - downTime
            val tapDistance = kotlin.math.sqrt((e.x - downX) * (e.x - downX) + (e.y - downY) * (e.y - downY))
            
            if (tapDuration < 200 && tapDistance < dragThreshold) {
                // 确实是单击
                when (currentGestureMode) {
                    GestureMode.NAVIGATION -> {
                        // 导航模式下的单击可能是选择操作
                        gestureListener?.onCanvasDoubleTap(e.x, e.y)
                    }
                    else -> {
                        // 其他模式的单击处理
                    }
                }
            }
            return true
        }
        
        override fun onLongPress(e: MotionEvent) {
            // 精确的长按检测和处理
            val longPressDistance = kotlin.math.sqrt((e.x - downX) * (e.x - downX) + (e.y - downY) * (e.y - downY))
            
            if (longPressDistance < dragThreshold && !isScaling && !isPanning) {
                // 确实是长按而不是拖拽
                isLongPressing = true
                
                when (currentGestureMode) {
                    GestureMode.DRAWING -> {
                        // 绘制模式下长按切换到橡皮擦
                        setGestureMode(GestureMode.ERASING)
                        gestureListener?.onToolLongPress(e.x, e.y)
                    }
                    GestureMode.NAVIGATION -> {
                        // 导航模式下长按可能是上下文菜单
                        gestureListener?.onToolLongPress(e.x, e.y)
                    }
                    else -> {
                        gestureListener?.onToolLongPress(e.x, e.y)
                    }
                }
            }
        }
        
        fun handleScroll(
            e1: MotionEvent?,
            e2: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            // 精确的滚动处理 - 只允许双指拖拽
            if (currentGestureMode == GestureMode.NAVIGATION && !isScaling && isMultiTouch && e2 != null && e2.pointerCount >= 2) {
                if (!isPanning) {
                    isPanning = true
                    // 使用双指中心点作为起始点
                    gestureListener?.onPanStart(lastTwoFingerCenterX, lastTwoFingerCenterY)
                }
                
                // 计算当前双指中心点
                val currentCenterX = (e2.getX(0) + e2.getX(1)) / 2f
                val currentCenterY = (e2.getY(0) + e2.getY(1)) / 2f
                
                // 计算双指中心点的移动距离
                val dx = currentCenterX - lastTwoFingerCenterX
                val dy = currentCenterY - lastTwoFingerCenterY
                
                // 应用滚动阻尼
                val dampedDx = dx * 0.8f
                val dampedDy = dy * 0.8f
                
                // 实时拖拽显示
                gestureListener?.onCanvasDrag(dampedDx, dampedDy)
                
                // 更新双指中心点
                lastTwoFingerCenterX = currentCenterX
                lastTwoFingerCenterY = currentCenterY
                
                return true
            }
            return false
        }
        
        fun handleFling(
            e1: MotionEvent?,
            e2: MotionEvent?,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            // 精确的惯性滑动处理
            if (currentGestureMode == GestureMode.NAVIGATION && !isScaling) {
                val absVelocityX = kotlin.math.abs(velocityX)
                val absVelocityY = kotlin.math.abs(velocityY)
                
                // 计算平移结束速度
                val endTime = System.currentTimeMillis()
                val duration = endTime - panStartTime
                val adjustedVelocityX = if (duration > 0) velocityX * 0.5f else 0f
                val adjustedVelocityY = if (duration > 0) velocityY * 0.5f else 0f
                
                if (isPanning) {
                    isPanning = false
                    gestureListener?.onPanEnd(adjustedVelocityX, adjustedVelocityY)
                }
                
                // 只有在速度足够大时才触发惯性滑动
                if (absVelocityX > panVelocityThreshold || absVelocityY > panVelocityThreshold) {
                    gestureListener?.onFling(adjustedVelocityX, adjustedVelocityY)
                    return true
                }
            }
            return false
        }
    }
    
    /**
     * 双击手势监听器
     */
    private inner class DoubleTapListener : GestureDetector.OnDoubleTapListener {
        
        override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
            return false
        }
        
        override fun onDoubleTap(e: MotionEvent): Boolean {
            // 双击缩放
            gestureListener?.onCanvasDoubleTap(e.x, e.y)
            return true
        }
        
        override fun onDoubleTapEvent(e: MotionEvent): Boolean {
            return false
        }
    }
    
    /**
     * 缩放手势监听器
     */
    private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        private var initialDistance = 0f
        private var lastDistance = 0f
        private var scaleStartTime = 0L
        private var scaleVelocity = 0f
        
        override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
            isScaling = true
            // 使用双指间距而不是系统的span
            initialDistance = lastTwoFingerDistance
            lastDistance = initialDistance
            scaleStartTime = System.currentTimeMillis()
            scaleVelocity = 0f
            setGestureMode(GestureMode.NAVIGATION)
            
            // 如果正在绘制，先结束绘制
            if (currentGestureMode == GestureMode.DRAWING) {
                gestureListener?.onDrawingEnd()
            }
            
            // 使用双指中心点作为焦点
            val focusX = lastTwoFingerCenterX
            val focusY = lastTwoFingerCenterY
            gestureListener?.onScaleStart(focusX, focusY)
            
            return true
        }
        
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            // 使用双指间距计算缩放因子
            val currentDistance = lastTwoFingerDistance
            if (lastDistance > 0 && currentDistance > 0) {
                val scaleFactor = currentDistance / lastDistance
                
                // 使用双指中心点作为焦点
                val focusX = lastTwoFingerCenterX
                val focusY = lastTwoFingerCenterY
                
                // 计算缩放速度
                val currentTime = System.currentTimeMillis()
                val timeDelta = currentTime - scaleStartTime
                if (timeDelta > 0) {
                    scaleVelocity = (scaleFactor - 1.0f) / timeDelta * 1000f
                }
                
                // 平滑缩放处理，避免跳跃
                val smoothScaleFactor = if (kotlin.math.abs(scaleFactor - 1.0f) > 0.1f) {
                    1.0f + (scaleFactor - 1.0f) * 0.5f // 减少缩放敏感度
                } else {
                    scaleFactor
                }
                
                // 应用缩放
                if (kotlin.math.abs(smoothScaleFactor - 1.0f) > 0.01f) {
                    gestureListener?.onCanvasScale(smoothScaleFactor, focusX, focusY)
                }
                
                lastDistance = currentDistance
            }
            
            return true
        }
        
        override fun onScaleEnd(detector: ScaleGestureDetector) {
            isScaling = false
            initialDistance = 0f
            lastDistance = 0f
            
            gestureListener?.onScaleEnd(scaleVelocity)
            scaleVelocity = 0f
            
            // 缩放结束后根据触摸点数量决定模式
            if (!isMultiTouch) {
                setGestureMode(GestureMode.DRAWING)
            }
        }
    }
    
    /**
     * 设置手势模式
     */
    fun setGestureMode(mode: GestureMode) {
        if (currentGestureMode != mode) {
            currentGestureMode = mode
            gestureListener?.onGestureModeChanged(mode)
        }
    }
    
    /**
     * 设置当前工具
     */
    fun setCurrentTool(tool: DrawingTool) {
        // 根据工具自动调整手势模式
        when (tool) {
            DrawingTool.PEN, DrawingTool.PENCIL, DrawingTool.HIGHLIGHTER -> {
                setGestureMode(GestureMode.DRAWING)
            }
            DrawingTool.ERASER -> {
                setGestureMode(GestureMode.ERASING)
            }
        }
        
        // 调整手势参数
        adjustGestureParameters(tool)
    }
    
    /**
     * 根据工具调整手势参数
     */
    private fun adjustGestureParameters(tool: DrawingTool) {
        when (tool) {
            DrawingTool.PEN -> {
                // 钢笔需要高精度
                dragThreshold = 3f
                longPressTimeout = 500L
            }
            DrawingTool.PENCIL -> {
                // 铅笔允许轻微抖动
                dragThreshold = 5f
                longPressTimeout = 400L
            }
            DrawingTool.HIGHLIGHTER -> {
                // 荧光笔较粗，容忍度更高
                dragThreshold = 8f
                longPressTimeout = 600L
            }
            DrawingTool.ERASER -> {
                // 橡皮擦需要较大的触发区域
                dragThreshold = 10f
                longPressTimeout = 300L
            }
        }
    }
    
    /**
     * 获取当前手势模式
     */
    fun getCurrentGestureMode(): GestureMode {
        return currentGestureMode
    }
    
    /**
     * 设置手势监听器
     */
    fun setGestureListener(listener: GestureCallback) {
        gestureListener = listener
    }
    
    /**
     * 设置缩放范围
     */
    fun setScaleRange(minScale: Float, maxScale: Float) {
        this.minScale = max(0.1f, minScale)
        this.maxScale = min(10f, maxScale)
    }
    
    /**
     * 设置拖拽阈值
     */
    fun setDragThreshold(threshold: Float) {
        dragThreshold = max(5f, threshold)
    }
    
    /**
     * 设置双击超时时间
     */
    fun setDoubleTapTimeout(timeout: Long) {
        doubleTapTimeout = max(100L, timeout)
    }
    
    /**
     * 设置长按超时时间
     */
    fun setLongPressTimeout(timeout: Long) {
        longPressTimeout = max(300L, timeout)
    }
    
    /**
     * 重置手势状态
     */
    fun reset() {
        currentGestureMode = GestureMode.DRAWING
        isDragging = false
        isScaling = false
        isLongPressing = false
        isMultiTouch = false
        isPanning = false
        isDrawing = false
        pointerCount = 0
        scaleFactor = 1.0f
        gestureStartTime = 0L
    }
    
    /**
     * 获取当前手势状态
     */
    fun getCurrentGestureState(): GestureState {
        return GestureState(
            isScaling = isScaling,
            isPanning = isPanning,
            isDrawing = isDrawing,
            isLongPressing = isLongPressing,
            currentMode = currentGestureMode,
            activePointers = pointerCount
        )
    }
    
    /**
     * 设置手势灵敏度
     */
    fun setGestureSensitivity(dragThreshold: Float, longPressTimeout: Long, scaleThreshold: Float) {
        this.dragThreshold = dragThreshold.coerceAtLeast(5f)
        this.longPressTimeout = longPressTimeout.coerceAtLeast(100L)
        this.scaleVelocityThreshold = scaleThreshold.coerceAtLeast(0.001f)
    }
    
    /**
     * 手势状态数据类
     */
    data class GestureState(
        val isScaling: Boolean,
        val isPanning: Boolean,
        val isDrawing: Boolean,
        val isLongPressing: Boolean,
        val currentMode: GestureMode,
        val activePointers: Int
    )
    
    /**
     * 检查是否正在进行手势操作
     */
    fun isGestureInProgress(): Boolean {
        return isDragging || isScaling || isLongPressing
    }
    
    /**
     * 获取手势统计信息
     */
    fun getStatistics(): GestureStatistics {
        return GestureStatistics(
            currentMode = currentGestureMode,
            isMultiTouch = isMultiTouch,
            pointerCount = pointerCount,
            isDragging = isDragging,
            isScaling = isScaling,
            scaleFactor = scaleFactor
        )
    }
    
    /**
     * 手势统计信息
     */
    data class GestureStatistics(
        val currentMode: GestureMode,
        val isMultiTouch: Boolean,
        val pointerCount: Int,
        val isDragging: Boolean,
        val isScaling: Boolean,
        val scaleFactor: Float
    )
}